/**
 * 焦点移动 临近原则
 * 通过每个元素与当前焦点元素的位置关系，算出下一个最适合得到焦点的元素
 */

/**
 * 获取最佳焦点元素
 * @param { object } focusedView 当前焦点元素
 * @param { array }  allFocus 所有可获得焦点元素
 * @param { string } direction 移动方向
 */
function getBestCandidateRect(focusedView, allFocus, direction) {
  const betterCandidateList = [];
  const insideRectList = [];
  for (let i = 0; i < allFocus.length; i++) {
    if (allFocus[i].hasFocus) { continue; }
    if (isBetterCandidate(focusedView, allFocus[i], direction)) { betterCandidateList.push(allFocus[i]); }
  }
  if (betterCandidateList.length < 2) { return betterCandidateList[0] || null; }
  betterCandidateList.forEach(v => {
    if (isInsideRect(focusedView, v, direction)) { insideRectList.push(v); }
  });
  if (insideRectList.length < 2) { return insideRectList[0] || null; }
  return betterRectSort(focusedView, insideRectList, direction)[0];
}

/**
 * 判定是否是最佳焦点元素
 * @param { object } focusedView 当前焦点元素
 * @param { array }  nextFocus 下一个焦点元素
 * @param { string } direction 移动方向
 */
function isBetterCandidate(focusedView, nextFocus, direction) {
  const { left: focusLeft, right: focusRight, top: focusTop, bottom: focusBottom } = focusedView.rect;
  const { left: nextLeft, right: nextRight, top: nextTop, bottom: nextBottom } = nextFocus.rect;
  const directionMap = {
    right() {
      return nextLeft > focusLeft && nextRight > focusRight;
    },
    left() {
      return nextLeft < focusLeft && nextRight < focusRight;
    },
    up() {
      return nextTop < focusTop && nextBottom < focusBottom;
    },
    down() {
      return nextTop > focusTop && nextBottom > focusBottom;
    }
  };
  return directionMap[direction]();
}

/**
 * 判定最佳焦点元素集中的元素是否在区域内
 * @param { object } focusedView 当前焦点元素
 * @param { array }  nextFocus 下一个焦点元素
 * @param { string } direction 移动方向
 */
function isInsideRect(focusedView, nextFocus, direction) {
  const { left: focusLeft, right: focusRight, top: focusTop, bottom: focusBottom } = focusedView.rect;
  const { left: nextLeft, right: nextRight, top: nextTop, bottom: nextBottom } = nextFocus.rect;
  switch (direction) {
    case 'left':
    case 'right':
      return nextBottom > focusTop && nextTop < focusBottom;
    case 'up':
    case 'down':
      return nextRight > focusLeft && nextLeft < focusRight;
  }
}
/**
 * 根据距离将最佳焦点元素集排序
 * @param { object } focusedView 当前焦点元素
 * @param { array } bestFocus 最佳焦点元素
 * @param { string } direction 移动方向
 */
function betterRectSort(focusedView, bestFocus, direction) {
  return bestFocus.sort(function(a, b) {
    let m, n;
    switch (direction) {
      case 'right':
        m = 13 * Math.pow(a.rect.left - focusedView.rect.right, 2) + Math.pow((focusedView.rect.top + focusedView.rect.height / 2) - (a.rect.top + a.rect.height / 2), 2);
        n = 13 * Math.pow(b.rect.left - focusedView.rect.right, 2) + Math.pow((focusedView.rect.top + focusedView.rect.height / 2) - (b.rect.top + b.rect.height / 2), 2);
        break;
      case 'left':
        m = 13 * Math.pow(a.rect.right - focusedView.rect.left, 2) + Math.pow((focusedView.rect.top + focusedView.rect.height / 2) - (a.rect.top + a.rect.height / 2), 2);
        n = 13 * Math.pow(b.rect.right - focusedView.rect.left, 2) + Math.pow((focusedView.rect.top + focusedView.rect.height / 2) - (b.rect.top + b.rect.height / 2), 2);
        break;
      case 'up':
        m = 13 * Math.pow(a.rect.bottom - focusedView.rect.top, 2) + Math.pow((focusedView.rect.left + focusedView.rect.width / 2) - (a.rect.left + a.rect.width / 2), 2);
        n = 13 * Math.pow(b.rect.bottom - focusedView.rect.top, 2) + Math.pow((focusedView.rect.left + focusedView.rect.width / 2) - (b.rect.left + b.rect.width / 2), 2);
        break;
      case 'down':
        m = 13 * Math.pow(a.rect.top - focusedView.rect.bottom, 2) + Math.pow((focusedView.rect.left + focusedView.rect.width / 2) - (a.rect.left + a.rect.width / 2), 2);
        n = 13 * Math.pow(b.rect.top - focusedView.rect.bottom, 2) + Math.pow((focusedView.rect.left + focusedView.rect.width / 2) - (b.rect.left + b.rect.width / 2), 2);
        break;
    }
    return m - n;
  });
}

module.exports = {
  getBestCandidateRect
};
